package top.superflow.core.pool.resource.imp


import top.superflow.core.config.DefaultConfigurable
import top.superflow.core.control.{BlackList, WhiteList}
import top.superflow.core.pool.imp.ResourcePoolConfig
import top.superflow.core.pool.resource.factory.defaults.DefaultResourcePoolFactory
import top.superflow.core.pool.resource.{ResourcePool, ResourcePoolManager}
import top.superflow.core.pool.{Pool, PoolManagerConfig}
import top.superflow.core.resource.PooledResource
import top.superflow.core.statis.Metrizable
import top.superflow.exception.RequestUnsupportedException
import top.superflow.lang.StringUtils
import top.superflow.log.Loggable

import scala.collection.mutable.Map
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Future, Promise}


class GlobalResourcePoolManager private(var poolManagerConfig: PoolManagerConfig) extends DefaultConfigurable[PoolManagerConfig]
                                                                  with ResourcePoolManager with Loggable{


  private val pools = Map[String, ResourcePool[_]]()

  def register(resourcePoole : ResourcePool[_]) : Future[Metrizable[_]] = ???
  
  def load(configurations : List[ResourcePoolConfig]) : Future[Metrizable[_]] = {
    val p = Promise[Metrizable[_]]()
    Future {
      for(config <- configurations){
        val resourcePool = DefaultResourcePoolFactory.getInstance.create(config)
        pools += (resourcePool.getKey -> resourcePool)
      }
      p success this
    }
    p.future
  }


  
  // Members declared in PoolManager
  def close(poolKey: String): Unit = ???
  def createPool(config: ResourcePoolConfig): Boolean = ???


  def getPool(configuration: ResourcePoolConfig) : ResourcePool[_] = {
    if(configuration == null){
      throw new RequestUnsupportedException("The configuration should not be null")
    }

    val resourceKey = configuration.getKey
    if(this.contain(resourceKey)){
      return this.pools.get(resourceKey).get
    }

    val newResourcePool = DefaultResourcePoolFactory.getInstance.create(configuration)
    pools += (resourceKey -> newResourcePool)

    newResourcePool
  }

  def contain(key : String) : Boolean = {
    if(StringUtils.isBlank(key)){
      return false
    }

    return this.pools.contains(key)
  }
  
  def getMetrics : Map[String, Any] = ???

  override def getPool(poolKey: String): Future[Pool[ResourcePoolConfig, PooledResource[_]]] = ???

  override def getBlackList: BlackList = ???

  override def getWhiteList: WhiteList = ???

  override def hotApplyPool(config: ResourcePoolConfig): Future[Metrizable[_]] = ???

  override def generatePoolKey(config: ResourcePoolConfig): String = ???

  override def getDetail: List[ResourcePoolConfig] = ???
}

object GlobalResourcePoolManager extends Loggable {
  private var instance : GlobalResourcePoolManager = _

  def init(poolManagerConfig: PoolManagerConfig): Unit ={
    if(poolManagerConfig == null){
      throw new RequestUnsupportedException("the poolManagerConfig should not be null!")
    }

    if(instance != null){
      throw new RequestUnsupportedException("The GlobalResourcePoolManager has been initialized already, why do it again!")
    }

    instance = new GlobalResourcePoolManager(poolManagerConfig)
  }

  def getInstance : GlobalResourcePoolManager = {
    if(instance == null){
      throw new RequestUnsupportedException("Please init GlobalResourcePoolManager by the method init and then invoke getInstance")
    }
    instance
  }
}
